home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 April: Mac OS SDK / Dev.CD Apr 98 SDK1.toast / Development Kits (Disc 1) / Macintosh Drag and Drop / Demo Applications / DragsAndLists / ListCode.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-04  |  11.3 KB  |  522 lines  |  [TEXT/MPS ]

  1.  
  2. #if defined(UseDumpFiles)
  3.     #include <DumpHeader.h>
  4. #endif
  5.  
  6.  
  7. #include <Drag.h>
  8. #include <Errors.h>
  9. #include "ListCode.h"
  10.  
  11.  
  12. enum {
  13.     kNumOfRows = 14, 
  14.     
  15.     kSourceListTopMargin = 20, 
  16.     kSourceListLeftMargin = 20,
  17.     kSourceListWidth = 80,
  18.  
  19.     kDestListTopMargin = 20, 
  20.     kDestListLeftMargin = 130,
  21.     kDestListWidth = 80
  22.  
  23.  
  24. };
  25.  
  26.  
  27. static ListHandle pSourceList, pDestList, pCurrentClickedList;
  28. ListClickLoopProcPtr    pDefaultClickLoop;
  29.  
  30.  
  31.  
  32. /*------------------------------------------------------------------*/
  33.  
  34. void AddToList(OSType theType, ListHandle list)
  35. {
  36.     Rect    dataRect;
  37.     Cell    cell;
  38.     short    nuRow;
  39.     short    stringSize = sizeof(OSType);
  40.  
  41.     if (list == NULL) Debugger();
  42.     dataRect = (*list)->dataBounds;
  43.     nuRow = LAddRow(1, dataRect.bottom, list);
  44.     SetPt(&cell, 0, nuRow);
  45.     LSetCell(&theType, sizeof(OSType), cell, list);
  46. }
  47.  
  48.  
  49. /*------------------------------------------------------------------*/
  50.  
  51. Boolean PtInDestList(Point localPt)
  52. {
  53.     Rect rct;
  54.     
  55.     rct = (*pDestList)->rView;
  56.  
  57.     return PtInRect(localPt, &(*pDestList)->rView);
  58. }
  59.  
  60.  
  61.  
  62. /*------------------------------------------------------------------*/
  63.  
  64. void GetDestListRect(Rect *rct)
  65. {
  66.     *rct = (*pDestList)->rView;
  67. }
  68.  
  69.  
  70. /*------------------------------------------------------------------*/
  71.  
  72. void BuildDestList(WindowPtr win)
  73. {
  74.     Rect boundsRect, dataRect;
  75.     Point    cellSize = {0, 0};
  76.     short     height;
  77.  
  78.     GetRectHeight(win, kNumOfRows, &height);
  79.  
  80.     SetRect(&boundsRect, kDestListLeftMargin, kDestListTopMargin,
  81.                 kDestListLeftMargin + kDestListWidth, kDestListTopMargin + height);    
  82.     SetRect(&dataRect, 0, 0, 1, 0);    
  83.  
  84.     pDestList = LNew(&boundsRect, &dataRect, cellSize, 0, win, 
  85.                         false, false, false, true);
  86.  
  87.  
  88.     if (pDestList != NULL)
  89.         LDoDraw(true, pDestList);
  90.     else 
  91.         Debugger();
  92.  
  93.     (*pDestList)->selFlags = lOnlyOne;
  94.  
  95.     (*pDestList)->lClickLoop = (ListClickLoopUPP) MyClickLoop;
  96. }
  97.  
  98.  
  99. /*------------------------------------------------------------------*/
  100.  
  101. void UpdateDestList()
  102. {
  103.     if (pDestList == NULL)  Debugger();
  104.     UpdateFrameList(pDestList);
  105. }
  106.  
  107.  
  108. /*------------------------------------------------------------------*/
  109.  
  110. static void HandleClickInDestList(WindowPtr win, Boolean newClick, 
  111.             Boolean doubleClick, Cell nuCell)
  112. {
  113. #pragma unused (doubleClick, win, newClick, nuCell)
  114. }
  115.  
  116.  
  117. /*------------------------------------------------------------------*/
  118.  
  119. void AddToDestList(OSType theType)
  120. {
  121.     AddToList(theType, pDestList);
  122. }
  123.  
  124.  
  125. /*------------------------------------------------------------------*/
  126.  
  127. void AddToSourceList(OSType theType)
  128. {
  129.     AddToList(theType, pSourceList);
  130. }
  131.  
  132.  
  133.  
  134. /*------------------------------------------------------------------*/
  135.  
  136. void BuildSourceList(WindowPtr win)
  137. {
  138.     Rect boundsRect, dataRect;
  139.     Point    cellSize = {0, 0};
  140.     short     height;
  141.  
  142.     GetRectHeight(win, kNumOfRows, &height);
  143.  
  144.     SetRect(&boundsRect, kSourceListLeftMargin, kSourceListTopMargin,
  145.                 kSourceListLeftMargin + kSourceListWidth,
  146.                 kSourceListTopMargin + height);    
  147.     SetRect(&dataRect, 0, 0, 1, 0);    
  148.  
  149.     pSourceList = LNew(&boundsRect, &dataRect, cellSize, 0, win, 
  150.                         false, false, false, true);
  151.  
  152.  
  153.     if (pSourceList != NULL)
  154.         LDoDraw(true, pSourceList);
  155.     else 
  156.         Debugger();
  157.     (*pSourceList)->selFlags = lOnlyOne;
  158.  
  159.     (*pSourceList)->lClickLoop = (ListClickLoopUPP) MyClickLoop;
  160. }
  161.  
  162.  
  163. /*------------------------------------------------------------------*/
  164.  
  165. void UpdateSourceList()
  166. {
  167.     if (pSourceList == NULL)  Debugger();
  168.     UpdateFrameList(pSourceList);
  169. }
  170.  
  171.  
  172. /*------------------------------------------------------------------*/
  173.  
  174. static void UpdateFrameList(ListHandle list)
  175. {
  176.     if (list != NULL) {
  177.         Rect listRect;
  178.         
  179.         listRect = (*list)->rView;
  180.         InsetRect(&listRect, -1, -1);
  181.         LUpdate((*list)->port->visRgn, list);
  182.         FrameRect(&listRect);
  183.     }
  184. }
  185.  
  186.  
  187.  
  188. /*------------------------------------------------------------------*/
  189.  
  190. static void HandleClickInSourceList(WindowPtr win, Boolean newClick, 
  191.             Boolean doubleClick, Cell nuCell)
  192. {
  193. #pragma unused (doubleClick, win, newClick, nuCell)
  194. }
  195.  
  196.  
  197. /*------------------------------------------------------------------*/
  198.  
  199. Boolean MyClickLoop()
  200. {
  201.     Point        localPt;
  202.     Cell        selectedCell;
  203.     ListHandle    list;
  204.  
  205.     list = pCurrentClickedList;
  206.     GetMouse(&localPt);    
  207.     if (GetFirstSelection(list, &selectedCell) == true) {
  208.         if (PtInRect(localPt, &(*list)->rView) == false) {
  209.             EventRecord    dummyEvent;
  210.             long        tmpLong;
  211.             Rect        tmpRect;
  212.             
  213.             OSEventAvail(0, &dummyEvent);
  214.             dummyEvent.what = mouseDown;
  215.             
  216.             //
  217.             // We go through the trouble of making sure the mouse doesn't
  218.             // appear outside of the list cell region when the drag starts.
  219.             //
  220.             // More purdy that way.
  221.             //
  222.             
  223.             GetSelectionRect(list, &tmpRect);
  224.             InsetRect(&tmpRect, 2, 2);
  225.             tmpLong = PinRect(&tmpRect, localPt);
  226.             dummyEvent.where = *(Point *) &tmpLong;
  227.             LocalToGlobal((Point *) &dummyEvent.where);
  228.             
  229.             //
  230.             // Now if we successfully drop the cell somewhere else,
  231.             // clear the selection in the original list.
  232.             //
  233.  
  234.             if (StartADrag(list, &dummyEvent) == noErr)
  235.                 LSetSelect(false, selectedCell, list);
  236.             
  237.             return false;
  238.             
  239.         }
  240.     }
  241.  
  242.     return true;
  243. }
  244.  
  245. /*------------------------------------------------------------------*/
  246.  
  247. OSErr AddFlavors(DragReference drag, ItemReference item, ListHandle list)
  248. {
  249.     OSType    selectedType;
  250.     short    dataSize;
  251.     Cell    selectedCell;
  252.  
  253.     SetPt((Point *) &selectedCell, 0, 0);
  254.     if (GetFirstSelection(list, &selectedCell) == false)
  255.         return paramErr;
  256.     
  257.     dataSize = sizeof(OSType);
  258.     LGetCell((Ptr) &selectedType, &dataSize, selectedCell, list);
  259.     
  260.     if (dataSize != sizeof(OSType))
  261.         return paramErr;
  262.     
  263.     return AddDragItemFlavor(drag, item, myPersonalFlavorType, 
  264.                         (Ptr) &selectedType, dataSize, flavorSenderOnly);
  265.  
  266. }
  267.  
  268.  
  269. /*------------------------------------------------------------------*/
  270.  
  271. OSErr StartADrag(ListHandle list, EventRecord *theEvent)
  272. {
  273.     OSErr            err;
  274.     DragReference    theDrag;
  275.     Rect            dragBounds;
  276.     RgnHandle        dragRgn;
  277.     ItemReference    theItem = 1;
  278.  
  279.     err = NewDrag(&theDrag);
  280.  
  281.     if (err == noErr) {        
  282.         err =  AddFlavors(theDrag, theItem, list);
  283.  
  284.         if (err == noErr) {
  285.  
  286.             if (GetSelectionRect(list, &dragBounds) == true) {
  287.                 LocalToGlobalRect(&dragBounds);                
  288.                 err = SetDragItemBounds(theDrag, theItem, &dragBounds);
  289.  
  290.                 if (err == noErr) {    
  291.                     dragRgn = NewRgn();
  292.                     RectRgn(dragRgn, &dragBounds);
  293.                     OutlineRegion(dragRgn);
  294.                     err = TrackDrag(theDrag, theEvent, dragRgn);
  295.                     
  296.                     DisposeRgn(dragRgn);
  297.                 }
  298.             }
  299.         }
  300.  
  301.         DisposeDrag(theDrag);
  302.     }
  303.  
  304.     return err;
  305. }
  306.  
  307.  
  308. /*------------------------------------------------------------------*/
  309.  
  310. Boolean GetFirstSelection(ListHandle list, Cell *cell)
  311. {
  312.  
  313.     SetPt((Point *) cell, 0, 0);
  314.     return LGetSelect(true, cell, list);
  315. }
  316.  
  317.  
  318. /*------------------------------------------------------------------*/
  319.  
  320. Boolean GetSelectionRect(ListHandle list, Rect *rct)
  321. {
  322.     Boolean    validSelection;
  323.     Cell    selectedCell, adjustedCell;
  324.     Rect    selectedCellRect, emptyRect = {0, 0, 0, 0};
  325.     
  326.     *rct = emptyRect;
  327.     validSelection = GetFirstSelection(list, &selectedCell);
  328.  
  329.     if (validSelection) {
  330.  
  331.         //
  332.         // adjustedCell is needed because the current view of the list may not
  333.         // have cell (0, 0) at the top left corner.  This takes the top and left
  334.         // values of the visible field and subtracts them from the selected cell,
  335.         // to give us this cell's location in the current view (honoring scroll bars).
  336.         //
  337.  
  338.         adjustedCell.v = selectedCell.v - (*list)->visible.top;
  339.         adjustedCell.h = selectedCell.h - (*list)->visible.left;
  340.  
  341.         selectedCellRect.top = (*list)->rView.top + (adjustedCell.v * (*list)->cellSize.v);
  342.         selectedCellRect.bottom = selectedCellRect.top + (*list)->cellSize.v;
  343.     
  344.         selectedCellRect.left = (*list)->rView.left + (adjustedCell.h * (*list)->cellSize.h);
  345.         selectedCellRect.right = selectedCellRect.left + (*list)->cellSize.h;
  346.  
  347.         *rct = selectedCellRect;
  348.     }
  349.     
  350.     return validSelection;
  351. }
  352.  
  353.  
  354. /*------------------------------------------------------------------*/
  355.  
  356. Boolean MouseHitSelection(ListHandle list, Point localPt)
  357. {
  358.     Cell        selectedCell;
  359.     Rect        selectedCellRect;
  360.  
  361.  
  362.     if (GetFirstSelection(list, &selectedCell) == false)
  363.         return false;
  364.  
  365.     if (PtInRect(* (Point *) &selectedCell, (Rect *) &(*list)->visible) == false)
  366.         return false;
  367.  
  368.     if (GetSelectionRect(list, &selectedCellRect) == false)
  369.         return false;
  370.  
  371.     return PtInRect(localPt, &selectedCellRect);    
  372.  
  373. }
  374.  
  375.  
  376. /*------------------------------------------------------------------*/
  377.  
  378. void OutlineRegion(RgnHandle theRgn)
  379. {
  380.     RgnHandle tempRgn;
  381.     
  382.     tempRgn = NewRgn();
  383.     CopyRgn(theRgn, tempRgn);
  384.     InsetRgn(tempRgn, 1, 1);
  385.     DiffRgn(theRgn, tempRgn, theRgn);
  386.     DisposeRgn(tempRgn);
  387. }
  388.  
  389.  
  390.  
  391. /*------------------------------------------------------------------*/
  392.  
  393. Boolean HandleListClick(WindowPtr win, EventRecord *event)
  394. {
  395.     Rect    listRect;
  396.     Point    localPt;
  397.     Boolean    handledClick;
  398.     long    numOfLists = 2, count;
  399.     ListHandle thisList, lists[2];
  400.     
  401.     lists[0] = pSourceList;
  402.     lists[1] = pDestList;
  403.     
  404.     handledClick = false;
  405.     localPt = event->where;
  406.     GlobalToLocal(&localPt);
  407.  
  408.     for (count = 0; (count < numOfLists) && (handledClick == false) ; count ++) {
  409.         thisList = lists[count];
  410.  
  411.         if ((*thisList)->lActive == true) {
  412.     
  413.             listRect = (*thisList)->rView;
  414.             if ((*thisList)->vScroll != NULL)    listRect.right += 15;
  415.             if ((*thisList)->hScroll != NULL)    listRect.bottom += 15;
  416.         
  417.             if (PtInRect(localPt, &listRect) == true) {    
  418.                 Cell        oldCell, nuCell;
  419.                 Boolean        oldSelection, 
  420.                             validSelection = false, 
  421.                             newClick = false, 
  422.                             doubleClick;
  423.  
  424.                 newClick = false;
  425.  
  426.                 oldSelection = GetFirstSelection(thisList, &oldCell);
  427.  
  428.                 if (MouseHitSelection(thisList, localPt)) {
  429.             
  430.                     //
  431.                     // Within this list, we may have a cell selected that the user
  432.                     // now wants to drag.  MouseHitSelection will first check if
  433.                     // the user wants to do such a thing, and if so it will start
  434.                     // the drag with the appropriate information.
  435.                     //
  436.                     // Now if we successfully drop the cell somewhere else,
  437.                     // clear the selection in the original list.
  438.                     //
  439.     
  440.                     if (StartADrag(thisList, event) == noErr)
  441.                         LSetSelect(false, oldCell, thisList);
  442.                     return true;
  443.                 }
  444.                 
  445.                 //
  446.                 // Save the current list for use in our click loop 
  447.                 //
  448.                 
  449.                 pCurrentClickedList = thisList;
  450.  
  451.                 doubleClick = LClick(localPt, event->modifiers, thisList);
  452.                 validSelection = GetFirstSelection(thisList, &nuCell);
  453.  
  454.                 if (validSelection == true) 
  455.                     if ((oldSelection == false) 
  456.                         || (EqualCells(nuCell, oldCell) == false))
  457.             
  458.                         newClick = true;
  459.  
  460.                 if (thisList == pSourceList)
  461.                     HandleClickInSourceList(win, newClick, doubleClick, nuCell);
  462.                 else
  463.                     HandleClickInDestList(win, newClick, doubleClick, nuCell);
  464.         
  465.                 handledClick = true;
  466.             }
  467.         }
  468.     }
  469.     return handledClick;
  470. }
  471.  
  472.  
  473. /*------------------------------------------------------------------*/
  474.  
  475. void GetRectHeight(WindowPtr win, short rows, short *height)
  476. {
  477. #pragma unused(win)
  478.     FontInfo fi;
  479.     
  480.     GetFontInfo(&fi);
  481.     *height = (fi.ascent + fi.descent + fi.leading) * rows;
  482. }
  483.  
  484.  
  485. /*------------------------------------------------------------------*/
  486.  
  487. static Boolean EqualCells(Cell c1, Cell c2)
  488. {
  489.     return ((c1.h == c2.h) && (c1.v == c2.v));
  490. }
  491.  
  492.  
  493. /*------------------------------------------------------------------*/
  494.  
  495. void GetGlobalMouse(Point *mouse)
  496. {
  497.     EventRecord    event;
  498.     
  499.     OSEventAvail(0, &event);
  500.     *mouse = event.where;
  501. }
  502.  
  503.  
  504. /*------------------------------------------------------------------*/
  505.  
  506. void GlobalToLocalRect(Rect *r)
  507. {
  508.     GlobalToLocal((Point*)(&r->top));
  509.     GlobalToLocal((Point*)(&r->bottom));
  510. }
  511.  
  512.  
  513. /*------------------------------------------------------------------*/
  514.  
  515. void LocalToGlobalRect(Rect *r)
  516. {
  517.     LocalToGlobal((Point*)(&r->top));
  518.     LocalToGlobal((Point*)(&r->bottom));
  519. }
  520.  
  521.  
  522.